let _Vue = null
export default class VueRouter {
    static install (Vue) {
        // 1.判断插件是否已经安装
        if (VueRouter.install.installed) {
            return
        }
        VueRouter.install.installed = true
        // 2.把 Vue 构造函数记录到全局变量
        _Vue = Vue
        // 3.把创建 Vue 实例时候传入的 router 对象注入到 Vue 实例上
       
        // 混入 为生命周期中的 beforeCreate 钩子函数挂载一个方法 
        // 当前的 this 指向 Vue 实例，实例中带有 $options.router 属性则为该实例的原型添加 $router 属性
        _Vue.mixin({
            beforeCreate () {
                if (this.$options.router) {
                    _Vue.prototype.$router = this.$options.router
                    this.$options.router.init()
                }
            }
        })
    }

    constructor (options) {
        // constructor 接受一个配置对象，并保存在 options 中
        this.options = options
        // 将 options 中的路由规则解析出来存储到 routeMap 中，routeMap 为键值对形式，键为路由地址，值为对应的组件
        // 根据当前 data 的路由地址，从 routeMap 中找到对应的组件渲染到浏览器中来
        this.routeMap = {}
        // data为响应式对象，Vue 提供了一个 observable() 静态方法将对象转换成响应式
        this.data = _Vue.observable({
            current: '/'
        })
    }

    init () {
        this.createRouteMap()
        this.initComponents(_Vue)
        this.initEvent()
    }

    createRouteMap () {
        // 遍历所有的路由规则，解析路由规则变成键值对形式存储到 routeMap 中
        this.options.routes.forEach(route => {
            this.routeMap[route.path] = route.component
        })
    }

    initComponents (Vue) {
        Vue.component('router-link', {
            props: {
                to: String
            },
            // template: '<a :href="to"><slot></slot></a>'
            render (h) {
                // h 为 vue 提供的函数，接受三个参数，标签名、属性、标签内容
                // attrs 为 DOM 属性
                // 标签内容可能有多个，所以是数组形式，this.$slots.default 为默认插槽
                return h('a', {
                    attrs: {
                        href: this.to
                    },
                    on: {
                        // 为标记注册 click 事件
                        click: this.clickHandler
                    }
                }, [this.$slots.default])
            },
            methods: {
                clickHandler (e) {
                    // 为浏览器改变地址栏但不会发送请求
                    // history.pushState 方法接受三个参数 data、title、url
                        // data 传给事件对象的参数
                        // title 网页标题
                        // url 当前超链接要跳转的地址
                    history.pushState({}, '', this.to)
                    // 将修改的路径修改到 Vue 实例的 data.current 中
                    this.$router.data.current = this.to
                    // 阻止默认行为
                    e.preventDefault()
                }
            }
        })

        const self = this
        Vue.component('router-view',{
            render (h) {
                // 在 render 方法内部 this 的指向发生了变化，需要在外部先保存this
                const component = self.routeMap[self.data.current]
                // h 函数能直接将组件转换成虚拟 DOM
                return h(component)
            }
        })
    }

    initEvent () {
        window.addEventListener('popstate', () => {
            // 将路径修改为历史记录
            this.data.current = window.location.pathname
        })
    }
}